<div class="selenium-notes">
<h1>Page Object Model (POM) in Selenium</h1>
<p><strong>Page Object Model (POM)</strong> is a design pattern used in Selenium automation testing to create maintainable, reusable, readable, and scalable automation scripts. In POM, every important page or reusable component of a web application is represented by a separate Java class. The class contains the locators and methods required to interact with that page or component.</p>
<p>The main purpose of POM is to separate <strong>test logic</strong> from <strong>page interaction logic</strong>. Instead of writing Selenium locators and WebDriver commands directly inside every test case, they are organized inside page classes. This reduces code duplication and makes automation scripts easier to maintain when the application's UI changes.</p>
<p>JustAcademy's Selenium Training covers <strong>Page Object Model (POM)</strong> as part of Selenium automation framework development, along with TestNG, Data-Driven Testing, Keyword-Driven Framework, Hybrid Framework Design, reusable test architecture, reporting, logging, debugging, Selenium Grid, and CI/CD concepts.</p>
<p><a href="https://www.justacademy.co/course-detail/selenium-training" target="_blank" rel="noopener noreferrer">Selenium Training</a> | <a href="https://www.justacademy.co/register-for-course-demo" target="_blank" rel="noopener noreferrer">Register for Course Demo</a></p>
<hr>
<h2>1. What Is Page Object Model?</h2>
<p>Page Object Model is a Selenium design pattern in which web pages are represented as Java classes. Each page class generally contains the locators of elements available on that page and methods that describe the actions that can be performed on those elements.</p>
<p>For example, if an application contains Login, Home, Product, Cart, and Checkout pages, we can create separate classes:</p>
<pre><code>LoginPage.java
HomePage.java
ProductPage.java
CartPage.java
CheckoutPage.java</code></pre>
<p>Each class represents the behavior and elements of its corresponding page.</p>
<hr>
<h2>2. Simple Definition</h2>
<p><strong>Page Object Model = Represent each application page as a reusable object containing its locators and page-specific actions.</strong></p>
<p>Instead of writing:</p>
<pre><code>driver.findElement(By.id("username"))
.sendKeys("testuser");
driver.findElement(By.id("password"))
.sendKeys("password");
driver.findElement(By.id("login"))
.click();</code></pre>
<p>inside every test, we can create a LoginPage class:</p>
<pre><code>LoginPage loginPage = new LoginPage(driver);
loginPage.enterUsername("testuser");
loginPage.enterPassword("password");
loginPage.clickLogin();</code></pre>
<hr>
<h2>3. Why Do We Need POM?</h2>
<p>Without POM, Selenium tests can become difficult to maintain because locators and WebDriver commands are repeated throughout multiple test classes.</p>
<pre><code>Test Case 1
↓
Login Locators
Test Case 2
↓
Login Locators
Test Case 3
↓
Login Locators
Test Case 4
↓
Login Locators</code></pre>
<p>If the login button's locator changes, multiple test cases may need to be updated.</p>
<p>With POM:</p>
<pre><code>LoginPage
↓
Login Locators
↓
Test Case 1
Test Case 2
Test Case 3
Test Case 4</code></pre>
<p>The locator can be maintained in one central location.</p>
<hr>
<h2>4. Main Objectives of POM</h2>
<ul>
<li>Separate test logic from page interaction logic.</li>
<li>Reduce duplicate Selenium code.</li>
<li>Centralize locators.</li>
<li>Improve test readability.</li>
<li>Improve maintainability.</li>
<li>Increase code reusability.</li>
<li>Make UI changes easier to manage.</li>
<li>Support scalable automation frameworks.</li>
<li>Improve collaboration among automation testers.</li>
<li>Make test cases easier to understand.</li>
</ul>
<hr>
<h2>5. Basic POM Architecture</h2>
<pre><code> Test Class
|
↓
Page Object
|
+-----------+-----------+
| |
Locators Methods
| |
+-----------+-----------+
|
↓
Selenium WebDriver
|
↓
Browser
|
↓
Web Application</code></pre>
<hr>
<h2>6. POM Components</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Component</th><th>Purpose</th></tr>
<tr><td>Page Class</td><td>Represents a web page or application component</td></tr>
<tr><td>Locators</td><td>Identify web elements</td></tr>
<tr><td>Page Methods</td><td>Perform actions on the page</td></tr>
<tr><td>WebDriver</td><td>Controls the browser</td></tr>
<tr><td>Test Class</td><td>Contains test scenarios and validations</td></tr>
<tr><td>Assertions</td><td>Validate expected results</td></tr>
</table>
<hr>
<h2>7. Example Application</h2>
<p>Consider an e-commerce application with the following pages:</p>
<pre><code>Login Page
↓
Home Page
↓
Search Page
↓
Product Page
↓
Cart Page
↓
Checkout Page</code></pre>
<p>Using POM, we can create:</p>
<pre><code>LoginPage.java
HomePage.java
SearchPage.java
ProductPage.java
CartPage.java
CheckoutPage.java</code></pre>
<hr>
<h2>8. Creating a LoginPage Class</h2>
<pre><code>package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class LoginPage {
private WebDriver driver;
private By username =
By.id("username");
private By password =
By.id("password");
private By loginButton =
By.id("login");
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void enterUsername(String value) {
driver.findElement(username)
.sendKeys(value);
}
public void enterPassword(String value) {
driver.findElement(password)
.sendKeys(value);
}
public void clickLogin() {
driver.findElement(loginButton)
.click();
}
public void login(String usernameValue,
String passwordValue) {
enterUsername(usernameValue);
enterPassword(passwordValue);
clickLogin();
}
}</code></pre>
<hr>
<h2>9. Understanding the LoginPage Class</h2>
<p>The class contains four important parts:</p>
<ol>
<li>WebDriver object.</li>
<li>Locators.</li>
<li>Constructor.</li>
<li>Page interaction methods.</li>
</ol>
<hr>
<h2>10. WebDriver Variable</h2>
<pre><code>private WebDriver driver;</code></pre>
<p>This variable stores the WebDriver instance used by the page object to interact with the browser.</p>
<hr>
<h2>11. Locators in POM</h2>
<p>Locators identify elements on a web page.</p>
<pre><code>private By username =
By.id("username");
private By password =
By.id("password");
private By loginButton =
By.id("login");</code></pre>
<p>Common Selenium locators include:</p>
<ul>
<li>id</li>
<li>name</li>
<li>className</li>
<li>tagName</li>
<li>linkText</li>
<li>partialLinkText</li>
<li>cssSelector</li>
<li>XPath</li>
</ul>
<hr>
<h2>12. Why Keep Locators Private?</h2>
<p>Locators are generally declared as <strong>private</strong> because the test should interact with the page through meaningful methods instead of directly manipulating internal locator definitions.</p>
<pre><code>private By username = By.id("username");</code></pre>
<p>The test uses:</p>
<pre><code>loginPage.enterUsername("testuser");</code></pre>
<p>instead of:</p>
<pre><code>driver.findElement(
By.id("username")
).sendKeys("testuser");</code></pre>
<hr>
<h2>13. Constructor in POM</h2>
<p>The constructor receives the WebDriver object from the test or base class.</p>
<pre><code>public LoginPage(WebDriver driver) {
this.driver = driver;
}</code></pre>
<p>This allows the page class to use the same browser session created by the test framework.</p>
<hr>
<h2>14. Page Methods</h2>
<p>Page methods represent actions that a user can perform on a page.</p>
<pre><code>public void enterUsername(String value) {
driver.findElement(username)
.sendKeys(value);
}
public void enterPassword(String value) {
driver.findElement(password)
.sendKeys(value);
}
public void clickLogin() {
driver.findElement(loginButton)
.click();
}</code></pre>
<hr>
<h2>15. Test Class Using POM</h2>
<pre><code>import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class LoginTest {
@Test
public void validLoginTest() {
WebDriver driver =
new ChromeDriver();
driver.get(
"https://example.com/login"
);
LoginPage loginPage =
new LoginPage(driver);
loginPage.enterUsername(
"testuser"
);
loginPage.enterPassword(
"password"
);
loginPage.clickLogin();
driver.quit();
}
}</code></pre>
<hr>
<h2>16. POM Test Execution Flow</h2>
<pre><code>TestNG Test
↓
Create WebDriver
↓
Open Application
↓
Create LoginPage Object
↓
Call Page Method
↓
Page Method Uses Locator
↓
Selenium WebDriver
↓
Browser
↓
Application</code></pre>
<hr>
<h2>17. POM With Login Method</h2>
<p>Instead of calling three separate methods from the test, we can create a reusable business action called <strong>login()</strong>.</p>
<pre><code>public void login(
String usernameValue,
String passwordValue) {
enterUsername(usernameValue);
enterPassword(passwordValue);
clickLogin();
}</code></pre>
<p>The test becomes:</p>
<pre><code>LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
"testuser",
"password"
);</code></pre>
<hr>
<h2>18. Why Business Methods Are Useful</h2>
<p>Business-level methods make test cases easier to read.</p>
<p>Instead of:</p>
<pre><code>enterUsername();
enterPassword();
clickLogin();</code></pre>
<p>the test can simply say:</p>
<pre><code>loginPage.login(
username,
password
);</code></pre>
<p>This describes the business action rather than exposing every low-level Selenium operation.</p>
<hr>
<h2>19. Creating a HomePage Class</h2>
<pre><code>package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class HomePage {
private WebDriver driver;
private By searchBox =
By.id("search");
private By logoutButton =
By.id("logout");
public HomePage(WebDriver driver) {
this.driver = driver;
}
public void searchProduct(String product) {
driver.findElement(searchBox)
.sendKeys(product);
}
public void logout() {
driver.findElement(logoutButton)
.click();
}
}</code></pre>
<hr>
<h2>20. Creating a ProductPage Class</h2>
<pre><code>package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class ProductPage {
private WebDriver driver;
private By addToCart =
By.id("addToCart");
public ProductPage(WebDriver driver) {
this.driver = driver;
}
public void addProductToCart() {
driver.findElement(addToCart)
.click();
}
}</code></pre>
<hr>
<h2>21. Creating a CartPage Class</h2>
<pre><code>package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class CartPage {
private WebDriver driver;
private By checkoutButton =
By.id("checkout");
private By cartTotal =
By.id("cartTotal");
public CartPage(WebDriver driver) {
this.driver = driver;
}
public void clickCheckout() {
driver.findElement(checkoutButton)
.click();
}
public String getCartTotal() {
return driver.findElement(cartTotal)
.getText();
}
}</code></pre>
<hr>
<h2>22. Creating a CheckoutPage Class</h2>
<pre><code>package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class CheckoutPage {
private WebDriver driver;
private By firstName =
By.id("firstName");
private By address =
By.id("address");
private By placeOrder =
By.id("placeOrder");
public CheckoutPage(WebDriver driver) {
this.driver = driver;
}
public void enterFirstName(String value) {
driver.findElement(firstName)
.sendKeys(value);
}
public void enterAddress(String value) {
driver.findElement(address)
.sendKeys(value);
}
public void placeOrder() {
driver.findElement(placeOrder)
.click();
}
}</code></pre>
<hr>
<h2>23. Complete E-Commerce Flow Using POM</h2>
<pre><code>LoginPage
↓
login()
↓
HomePage
↓
searchProduct()
↓
ProductPage
↓
addProductToCart()
↓
CartPage
↓
clickCheckout()
↓
CheckoutPage
↓
placeOrder()</code></pre>
<hr>
<h2>24. Complete Test Example</h2>
<pre><code>import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.Test;
public class ECommerceTest {
@Test
public void purchaseProduct() {
WebDriver driver =
new ChromeDriver();
driver.manage()
.window()
.maximize();
driver.get(
"https://example.com"
);
LoginPage loginPage =
new LoginPage(driver);
HomePage homePage =
new HomePage(driver);
ProductPage productPage =
new ProductPage(driver);
CartPage cartPage =
new CartPage(driver);
CheckoutPage checkoutPage =
new CheckoutPage(driver);
loginPage.login(
"testuser",
"password"
);
homePage.searchProduct(
"Laptop"
);
productPage.addProductToCart();
cartPage.clickCheckout();
checkoutPage.enterFirstName(
"Test User"
);
checkoutPage.enterAddress(
"Mumbai"
);
checkoutPage.placeOrder();
driver.quit();
}
}</code></pre>
<hr>
<h2>25. POM With TestNG</h2>
<p>POM is commonly used together with TestNG in Selenium automation frameworks.</p>
<pre><code>public class LoginTest extends BaseTest {
@Test
public void validLogin() {
LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
"testuser",
"password"
);
}
}</code></pre>
<hr>
<h2>26. Base Test With POM</h2>
<p>A BaseTest class can handle common browser setup and teardown.</p>
<pre><code>import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.*;
public class BaseTest {
protected WebDriver driver;
@BeforeMethod
public void setUp() {
driver = new ChromeDriver();
driver.manage()
.window()
.maximize();
driver.get(
"https://example.com"
);
}
@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}</code></pre>
<hr>
<h2>27. Login Test Extending BaseTest</h2>
<pre><code>public class LoginTest extends BaseTest {
@Test
public void validLoginTest() {
LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
"testuser",
"password"
);
}
}</code></pre>
<hr>
<h2>28. POM With Assertions</h2>
<p>Assertions should generally remain in the test or validation layer rather than being unnecessarily mixed into low-level page interaction methods.</p>
<pre><code>import org.testng.Assert;
import org.testng.annotations.Test;
public class LoginTest extends BaseTest {
@Test
public void verifyLogin() {
LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
"testuser",
"password"
);
Assert.assertEquals(
driver.getTitle(),
"Home Page"
);
}
}</code></pre>
<hr>
<h2>29. POM With Page Verification Methods</h2>
<p>Page classes can expose meaningful state-check methods when they are useful for test readability.</p>
<pre><code>public boolean isLogoutButtonDisplayed() {
return driver.findElement(
logoutButton
).isDisplayed();
}</code></pre>
<p>The test can then use:</p>
<pre><code>Assert.assertTrue(
homePage.isLogoutButtonDisplayed()
);</code></pre>
<hr>
<h2>30. POM With Explicit Wait</h2>
<p>For modern dynamic applications, page objects often use explicit waits before interacting with elements.</p>
<pre><code>import java.time.Duration;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.*;
public class LoginPage {
private WebDriver driver;
private WebDriverWait wait;
private By username =
By.id("username");
private By password =
By.id("password");
private By loginButton =
By.id("login");
public LoginPage(WebDriver driver) {
this.driver = driver;
wait = new WebDriverWait(
driver,
Duration.ofSeconds(10)
);
}
public void enterUsername(String value) {
wait.until(
ExpectedConditions
.visibilityOfElementLocated(
username
)
).sendKeys(value);
}
public void enterPassword(String value) {
wait.until(
ExpectedConditions
.visibilityOfElementLocated(
password
)
).sendKeys(value);
}
public void clickLogin() {
wait.until(
ExpectedConditions
.elementToBeClickable(
loginButton
)
).click();
}
}</code></pre>
<hr>
<h2>31. POM With PageFactory</h2>
<p>Selenium projects may also use the PageFactory style of declaring page elements.</p>
<pre><code>import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.*;
public class LoginPage {
private WebDriver driver;
@FindBy(id = "username")
private WebElement username;
@FindBy(id = "password")
private WebElement password;
@FindBy(id = "login")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(
driver,
this
);
}
public void login(
String user,
String pass) {
username.sendKeys(user);
password.sendKeys(pass);
loginButton.click();
}
}</code></pre>
<hr>
<h2>32. By Locator vs WebElement</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Approach</th><th>Example</th><th>Common Use</th></tr>
<tr><td>By Locator</td><td>By.id("username")</td><td>Explicit locator-based interaction</td></tr>
<tr><td>WebElement</td><td>WebElement username</td><td>PageFactory-style page objects</td></tr>
</table>
<p>Both approaches can be used to implement page objects. The choice should be consistent with the project's framework standards.</p>
<hr>
<h2>33. POM With XPath</h2>
<pre><code>private By username =
By.xpath("//input[@name='username']");
private By loginButton =
By.xpath("//button[@type='submit']");</code></pre>
<p>Prefer stable and meaningful locators whenever possible.</p>
<hr>
<h2>34. POM With CSS Selector</h2>
<pre><code>private By username =
By.cssSelector("#username");
private By loginButton =
By.cssSelector("button[type='submit']");</code></pre>
<hr>
<h2>35. POM With Dropdowns</h2>
<pre><code>import org.openqa.selenium.support.ui.Select;
private By countryDropdown =
By.id("country");
public void selectCountry(String country) {
Select select =
new Select(
driver.findElement(
countryDropdown
)
);
select.selectByVisibleText(country);
}</code></pre>
<hr>
<h2>36. POM With Checkboxes</h2>
<pre><code>private By termsCheckbox =
By.id("terms");
public void selectTerms() {
WebElement checkbox =
driver.findElement(
termsCheckbox
);
if (!checkbox.isSelected()) {
checkbox.click();
}
}</code></pre>
<hr>
<h2>37. POM With Radio Buttons</h2>
<pre><code>private By maleRadio =
By.id("male");
public void selectMale() {
WebElement radio =
driver.findElement(maleRadio);
if (!radio.isSelected()) {
radio.click();
}
}</code></pre>
<hr>
<h2>38. POM With Alerts</h2>
<pre><code>public void acceptAlert() {
driver.switchTo()
.alert()
.accept();
}</code></pre>
<hr>
<h2>39. POM With Frames</h2>
<pre><code>public void switchToPaymentFrame() {
driver.switchTo()
.frame("paymentFrame");
}
public void switchToMainPage() {
driver.switchTo()
.defaultContent();
}</code></pre>
<hr>
<h2>40. POM With Multiple Windows</h2>
<pre><code>public void switchToNewWindow() {
String parent =
driver.getWindowHandle();
for (String window :
driver.getWindowHandles()) {
if (!window.equals(parent)) {
driver.switchTo()
.window(window);
}
}
}</code></pre>
<hr>
<h2>41. POM With Mouse Actions</h2>
<pre><code>import org.openqa.selenium.interactions.Actions;
public void hoverOverMenu(By locator) {
WebElement element =
driver.findElement(locator);
Actions actions =
new Actions(driver);
actions.moveToElement(element)
.perform();
}</code></pre>
<hr>
<h2>42. POM With JavaScript</h2>
<pre><code>import org.openqa.selenium.JavascriptExecutor;
public void scrollToElement(
WebElement element) {
JavascriptExecutor js =
(JavascriptExecutor) driver;
js.executeScript(
"arguments[0].scrollIntoView(true);",
element
);
}</code></pre>
<hr>
<h2>43. POM With Data-Driven Testing</h2>
<p>POM can be combined with Data-Driven Testing. The page class handles UI interaction while external data provides different input values.</p>
<pre><code>@DataProvider(name = "loginData")
public Object[][] loginData() {
return new Object[][] {
{"user1", "pass1"},
{"user2", "pass2"},
{"user3", "pass3"}
};
}
@Test(dataProvider = "loginData")
public void loginTest(
String username,
String password) {
LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
username,
password
);
}</code></pre>
<hr>
<h2>44. POM With Excel</h2>
<p>Excel can store multiple sets of test data while POM handles the page interactions.</p>
<pre><code>Excel
↓
Excel Utility
↓
TestNG DataProvider
↓
Test Class
↓
LoginPage
↓
Selenium WebDriver
↓
Browser</code></pre>
<hr>
<h2>45. POM With Keyword-Driven Framework</h2>
<p>POM can also be combined with a Keyword-Driven Framework.</p>
<pre><code>Keyword
↓
Keyword Library
↓
Page Object
↓
Selenium WebDriver
↓
Browser</code></pre>
<p>For example:</p>
<pre><code>Keyword: LOGIN
↓
LoginKeywords.login()
↓
LoginPage.login()
↓
Selenium WebDriver</code></pre>
<hr>
<h2>46. POM With Hybrid Framework</h2>
<p>POM is commonly used as one component of a Hybrid Framework.</p>
<pre><code> Hybrid Framework
|
+-------------+-------------+
| | |
POM Data-Driven Keyword-Driven
| | |
+-------------+-------------+
|
TestNG
|
Selenium WebDriver
|
Browser</code></pre>
<hr>
<h2>47. POM and Separation of Concerns</h2>
<p>One of the most important principles of POM is separation of responsibilities.</p>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Layer</th><th>Responsibility</th></tr>
<tr><td>Test Layer</td><td>Test scenario and validation</td></tr>
<tr><td>Page Layer</td><td>Page locators and page actions</td></tr>
<tr><td>Utility Layer</td><td>Reusable helper operations</td></tr>
<tr><td>Data Layer</td><td>Test data</td></tr>
<tr><td>Configuration Layer</td><td>Environment settings</td></tr>
<tr><td>Driver Layer</td><td>WebDriver creation and management</td></tr>
</table>
<hr>
<h2>48. Recommended POM Project Structure</h2>
<pre><code>SeleniumPOMFramework/
│
├── src/test/java/
│ ├── base/
│ │ └── BaseTest.java
│ │
│ ├── pages/
│ │ ├── LoginPage.java
│ │ ├── HomePage.java
│ │ ├── SearchPage.java
│ │ ├── ProductPage.java
│ │ ├── CartPage.java
│ │ └── CheckoutPage.java
│ │
│ ├── tests/
│ │ ├── LoginTest.java
│ │ ├── SearchTest.java
│ │ └── CheckoutTest.java
│ │
│ └── utilities/
│ ├── WaitUtil.java
│ ├── ExcelUtil.java
│ ├── ScreenshotUtil.java
│ └── ConfigReader.java
│
├── src/test/resources/
│ ├── config.properties
│ ├── testdata.xlsx
│ └── testng.xml
│
├── reports/
├── screenshots/
├── logs/
├── pom.xml
└── README.md</code></pre>
<hr>
<h2>49. Role of BaseTest</h2>
<p>BaseTest contains common setup and teardown operations.</p>
<ul>
<li>Initialize WebDriver.</li>
<li>Open browser.</li>
<li>Configure browser.</li>
<li>Open application URL.</li>
<li>Close browser.</li>
<li>Provide common framework setup.</li>
</ul>
<hr>
<h2>50. Role of Page Classes</h2>
<p>Page classes contain:</p>
<ul>
<li>Page-specific locators.</li>
<li>Page-specific actions.</li>
<li>Reusable business methods related to that page.</li>
<li>Page-level synchronization when appropriate.</li>
<li>Page-level state or validation methods when useful.</li>
</ul>
<hr>
<h2>51. Role of Test Classes</h2>
<p>Test classes should focus on test scenarios rather than low-level Selenium implementation.</p>
<pre><code>@Test
public void validLoginTest() {
LoginPage loginPage =
new LoginPage(driver);
loginPage.login(
"testuser",
"password"
);
Assert.assertTrue(
homePage.isLogoutButtonDisplayed()
);
}</code></pre>
<hr>
<h2>52. POM With Configuration File</h2>
<p>Application URLs and environment-specific settings can be kept outside the page classes.</p>
<pre><code>browser=chrome
url=https://qa.example.com
timeout=10</code></pre>
<p>This allows the framework to change environments without modifying individual page objects.</p>
<hr>
<h2>53. POM With Driver Factory</h2>
<pre><code>public class DriverFactory {
public static WebDriver createDriver(
String browser) {
if (browser.equalsIgnoreCase("chrome")) {
return new ChromeDriver();
}
if (browser.equalsIgnoreCase("firefox")) {
return new FirefoxDriver();
}
if (browser.equalsIgnoreCase("edge")) {
return new EdgeDriver();
}
throw new IllegalArgumentException(
"Unsupported browser: " + browser
);
}
}</code></pre>
<p>The page objects do not need to know how the browser was created. They simply receive a WebDriver instance.</p>
<hr>
<h2>54. POM With Page Navigation</h2>
<p>A page method can return another page object when an action navigates to a different page.</p>
<pre><code>public HomePage clickLogin() {
driver.findElement(
loginButton
).click();
return new HomePage(driver);
}</code></pre>
<p>The test can then write:</p>
<pre><code>HomePage homePage =
loginPage.clickLogin();</code></pre>
<p>This style can make page transitions explicit.</p>
<hr>
<h2>55. Fluent Page Object Model</h2>
<p>In a Fluent POM approach, page methods can return the same page object to allow method chaining.</p>
<pre><code>public LoginPage enterUsername(
String value) {
username.sendKeys(value);
return this;
}
public LoginPage enterPassword(
String value) {
password.sendKeys(value);
return this;
}
public HomePage clickLogin() {
loginButton.click();
return new HomePage(driver);
}</code></pre>
<p>Usage:</p>
<pre><code>HomePage homePage =
loginPage
.enterUsername("user")
.enterPassword("pass")
.clickLogin();</code></pre>
<hr>
<h2>56. POM With Component Objects</h2>
<p>Modern applications may contain reusable components such as headers, menus, search bars, sidebars, cards, and navigation bars. These can also be represented as reusable objects.</p>
<pre><code>HeaderComponent.java
NavigationComponent.java
SearchComponent.java
ProductCard.java
FooterComponent.java</code></pre>
<p>This is useful when the same UI component appears on many pages.</p>
<hr>
<h2>57. Page Object vs Component Object</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Page Object</th><th>Component Object</th></tr>
<tr><td>Represents a page or major screen</td><td>Represents a reusable UI component</td></tr>
<tr><td>Example: LoginPage</td><td>Example: HeaderComponent</td></tr>
<tr><td>Usually page-specific</td><td>Can be reused across pages</td></tr>
</table>
<hr>
<h2>58. POM Locator Maintenance</h2>
<p>Suppose the login button changes from:</p>
<pre><code>By.id("login")</code></pre>
<p>to:</p>
<pre><code>By.id("loginButton")</code></pre>
<p>With POM, the locator can be updated in the LoginPage class instead of searching through every test class for the old locator.</p>
<hr>
<h2>59. Without POM vs With POM</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Without POM</th><th>With POM</th></tr>
<tr><td>Locators often repeated</td><td>Locators centralized</td></tr>
<tr><td>Test classes contain UI logic</td><td>Page classes contain UI logic</td></tr>
<tr><td>Higher duplication</td><td>Lower duplication</td></tr>
<tr><td>Harder maintenance</td><td>Easier maintenance</td></tr>
<tr><td>Less readable tests</td><td>More readable tests</td></tr>
<tr><td>Limited reusability</td><td>Higher reusability</td></tr>
</table>
<hr>
<h2>60. Advantages of POM</h2>
<ul>
<li><strong>Maintainability:</strong> Locators are centralized in page classes.</li>
<li><strong>Reusability:</strong> Page methods can be reused by multiple tests.</li>
<li><strong>Readability:</strong> Tests describe business actions more clearly.</li>
<li><strong>Reduced duplication:</strong> Common actions do not need to be rewritten.</li>
<li><strong>Scalability:</strong> New pages can be added as separate classes.</li>
<li><strong>Easy debugging:</strong> Page-specific issues can be isolated.</li>
<li><strong>Better organization:</strong> Test and page logic are separated.</li>
<li><strong>Team collaboration:</strong> Different team members can work on different page objects and tests.</li>
</ul>
<hr>
<h2>61. Disadvantages of POM</h2>
<ul>
<li>Initial framework setup takes additional time.</li>
<li>Large applications may require many page classes.</li>
<li>Poorly designed page objects can become too large.</li>
<li>Frequent UI changes can still require page-object maintenance.</li>
<li>Excessive abstraction can make a framework difficult to understand.</li>
</ul>
<hr>
<h2>62. Common POM Mistakes</h2>
<ul>
<li>Putting complete test scenarios inside page classes.</li>
<li>Putting assertions everywhere in page methods.</li>
<li>Creating one extremely large page class.</li>
<li>Duplicating locators.</li>
<li>Using unstable locators.</li>
<li>Hard-coding test data unnecessarily.</li>
<li>Using Thread.sleep() instead of appropriate waits.</li>
<li>Mixing browser setup with page-specific logic.</li>
<li>Creating methods that perform unrelated actions.</li>
<li>Returning incorrect page objects after navigation.</li>
</ul>
<hr>
<h2>63. Best Practices for POM</h2>
<ul>
<li>Keep one logical page or component per class.</li>
<li>Use meaningful class names.</li>
<li>Keep locators private.</li>
<li>Use meaningful method names.</li>
<li>Keep page methods focused.</li>
<li>Use stable locators.</li>
<li>Use explicit waits where synchronization is required.</li>
<li>Keep test data outside page classes.</li>
<li>Keep browser initialization in a dedicated layer.</li>
<li>Keep assertions primarily in the test or validation layer.</li>
<li>Avoid unnecessarily large page classes.</li>
<li>Reuse common components.</li>
<li>Follow consistent coding standards.</li>
</ul>
<hr>
<h2>64. POM Naming Conventions</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Type</th><th>Example</th></tr>
<tr><td>Page Class</td><td>LoginPage</td></tr>
<tr><td>Test Class</td><td>LoginTest</td></tr>
<tr><td>Utility</td><td>ExcelUtil</td></tr>
<tr><td>Factory</td><td>DriverFactory</td></tr>
<tr><td>Method</td><td>enterUsername()</td></tr>
<tr><td>Locator Variable</td><td>loginButton</td></tr>
</table>
<hr>
<h2>65. POM Package Structure</h2>
<pre><code>src/test/java
│
├── base
│ └── BaseTest.java
│
├── pages
│ ├── LoginPage.java
│ ├── HomePage.java
│ ├── ProductPage.java
│ └── CartPage.java
│
├── tests
│ ├── LoginTest.java
│ ├── ProductTest.java
│ └── CartTest.java
│
└── utilities
├── ExcelUtil.java
├── WaitUtil.java
└── ScreenshotUtil.java</code></pre>
<hr>
<h2>66. POM With Reporting</h2>
<p>Reporting should generally be implemented outside individual page classes. The page objects perform actions, while listeners or reporting utilities capture test execution information.</p>
<pre><code>Test
↓
Page Object
↓
WebDriver
↓
Application
↓
Test Result
↓
Listener
↓
Report</code></pre>
<hr>
<h2>67. POM With Screenshots</h2>
<p>A screenshot utility can be used independently of the page classes.</p>
<pre><code>public class ScreenshotUtil {
public static void capture(
WebDriver driver,
String fileName) {
try {
TakesScreenshot ts =
(TakesScreenshot) driver;
File source =
ts.getScreenshotAs(
OutputType.FILE
);
File destination =
new File(
"screenshots/"
+ fileName
+ ".png"
);
FileUtils.copyFile(
source,
destination
);
} catch (Exception e) {
e.printStackTrace();
}
}
}</code></pre>
<hr>
<h2>68. POM With Logging</h2>
<p>Logging can be added around important framework actions.</p>
<pre><code>logger.info("Entering username");
logger.info("Entering password");
logger.info("Clicking Login button");
logger.info("Login action completed");</code></pre>
<p>The logging implementation should remain consistent with the framework's logging architecture.</p>
<hr>
<h2>69. POM With Selenium Grid</h2>
<p>POM is independent of the physical browser location. The WebDriver can be local or remote, while page objects continue to use the WebDriver interface.</p>
<pre><code>Test
↓
Page Object
↓
WebDriver
↓
Remote WebDriver
↓
Selenium Grid
↓
Browser Node
↓
Application</code></pre>
<hr>
<h2>70. POM With Cross-Browser Testing</h2>
<p>The same page objects can generally be reused across Chrome, Firefox, and Edge when the application behavior and locators are compatible.</p>
<pre><code> Page Objects
|
WebDriver API
|
+-----------+-----------+
| | |
Chrome Firefox Edge
| | |
+-----------+-----------+
|
Web Application</code></pre>
<hr>
<h2>71. POM With CI/CD</h2>
<p>A POM-based framework can be executed through Maven in a CI/CD pipeline.</p>
<pre><code>Git
↓
Jenkins
↓
Maven
↓
TestNG
↓
POM Tests
↓
Selenium WebDriver
↓
Browser
↓
Reports
↓
Build Result</code></pre>
<p>JustAcademy's Selenium Training includes POM along with automation framework concepts such as Maven, Git, Jenkins, Selenium Grid, reporting, and CI/CD.</p>
<hr>
<h2>72. POM vs Normal Selenium Script</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Aspect</th><th>Normal Script</th><th>POM</th></tr>
<tr><td>Locators</td><td>Often inside test</td><td>Centralized in page class</td></tr>
<tr><td>Page Actions</td><td>Often inside test</td><td>Page methods</td></tr>
<tr><td>Reusability</td><td>Limited</td><td>High</td></tr>
<tr><td>Maintenance</td><td>Can become difficult</td><td>More organized</td></tr>
<tr><td>Readability</td><td>Lower for large tests</td><td>Higher</td></tr>
<tr><td>Scalability</td><td>Limited</td><td>Better suited to larger suites</td></tr>
</table>
<hr>
<h2>73. POM vs Data-Driven Framework</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>POM</th><th>Data-Driven Framework</th></tr>
<tr><td>Design pattern</td><td>Testing technique/framework approach</td></tr>
<tr><td>Focuses on page organization</td><td>Focuses on test-data separation</td></tr>
<tr><td>Manages page objects</td><td>Manages multiple input datasets</td></tr>
<tr><td>Can be combined with Data-Driven Testing</td><td>Can use POM for UI interaction</td></tr>
</table>
<hr>
<h2>74. POM vs Keyword-Driven Framework</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>POM</th><th>Keyword-Driven</th></tr>
<tr><td>Represents pages/components</td><td>Represents reusable actions as keywords</td></tr>
<tr><td>Manages locators and page actions</td><td>Manages action execution</td></tr>
<tr><td>Can be used independently</td><td>Can use POM underneath</td></tr>
<tr><td>Often part of larger framework</td><td>Can be part of Hybrid Framework</td></tr>
</table>
<hr>
<h2>75. POM and Hybrid Framework Relationship</h2>
<p>POM is not itself a complete Hybrid Framework. It is a design pattern that can be used as a major layer inside a larger automation framework.</p>
<pre><code>Hybrid Framework
|
+-- TestNG
|
+-- POM
|
+-- Data-Driven
|
+-- Keyword-Driven
|
+-- Utilities
|
+-- Reporting
|
+-- Logging
|
+-- CI/CD</code></pre>
<hr>
<h2>76. Real-Time POM Architecture</h2>
<pre><code> TestNG
|
Test Classes
|
Page Objects
|
+--------------+--------------+
| | |
Locators Actions Validations
| | |
+--------------+--------------+
|
Selenium WebDriver
|
Driver Factory
|
+------------+------------+
| | |
Chrome Firefox Edge
|
Web Application
|
+--------------+--------------+
| | |
Reports Logs Screenshots</code></pre>
<hr>
<h2>77. Practical Project: Login Automation Using POM</h2>
<h3>Project Objective</h3>
<p>Create a Selenium automation framework that validates different login scenarios using Page Object Model and TestNG.</p>
<h3>Test Scenarios</h3>
<ul>
<li>Valid username and valid password.</li>
<li>Invalid username and valid password.</li>
<li>Valid username and invalid password.</li>
<li>Invalid username and invalid password.</li>
<li>Blank username.</li>
<li>Blank password.</li>
<li>Both fields blank.</li>
</ul>
<hr>
<h2>78. Login Project Structure</h2>
<pre><code>LoginAutomation/
│
├── src/test/java/
│ ├── base/
│ │ └── BaseTest.java
│ ├── pages/
│ │ └── LoginPage.java
│ └── tests/
│ └── LoginTest.java
│
├── src/test/resources/
│ └── config.properties
│
├── pom.xml
└── testng.xml</code></pre>
<hr>
<h2>79. Practical Assignment: E-Commerce POM</h2>
<p>Create a POM-based automation project for an e-commerce application.</p>
<h3>Pages to Create</h3>
<ol>
<li>LoginPage</li>
<li>HomePage</li>
<li>SearchPage</li>
<li>ProductPage</li>
<li>CartPage</li>
<li>CheckoutPage</li>
<li>OrderConfirmationPage</li>
</ol>
<h3>Test Flow</h3>
<pre><code>Login
↓
Search Product
↓
Open Product
↓
Add Product
↓
Open Cart
↓
Checkout
↓
Place Order
↓
Verify Confirmation</code></pre>
<hr>
<h2>80. POM Interview Questions</h2>
<h3>Q1. What is Page Object Model?</h3>
<p>Page Object Model is a design pattern in Selenium where application pages or components are represented by classes containing their locators and interaction methods.</p>
<h3>Q2. Why is POM used?</h3>
<p>POM is used to improve maintainability, readability, reusability, and separation of test logic from page interaction logic.</p>
<h3>Q3. What does a Page Object contain?</h3>
<p>A Page Object commonly contains page-specific locators, WebDriver interactions, and reusable page/business methods.</p>
<h3>Q4. Should test cases contain locators?</h3>
<p>In a well-structured POM framework, page-specific locators are generally maintained in page classes rather than repeated throughout test classes.</p>
<h3>Q5. What is the advantage of private locators?</h3>
<p>Private locators provide encapsulation and encourage tests to interact with pages through meaningful page methods.</p>
<hr>
<h2>81. More POM Interview Questions</h2>
<h3>Q6. What is the role of the constructor in POM?</h3>
<p>The constructor commonly receives the WebDriver instance and stores it so page methods can interact with the browser.</p>
<h3>Q7. Can POM be combined with Data-Driven Testing?</h3>
<p>Yes. Test data can be supplied through TestNG DataProvider, Excel, CSV, JSON, or other sources while page objects handle UI interaction.</p>
<h3>Q8. Can POM be combined with Keyword-Driven Testing?</h3>
<p>Yes. Keyword methods can call page-object methods to implement reusable business actions.</p>
<h3>Q9. Can POM be used with TestNG?</h3>
<p>Yes. TestNG can manage test execution while POM organizes page-level interactions.</p>
<h3>Q10. Can POM be used in a Hybrid Framework?</h3>
<p>Yes. POM is commonly used as one of the core layers of a Hybrid Selenium Framework.</p>
<hr>
<h2>82. Advanced POM Interview Questions</h2>
<h3>Q11. What happens if a locator changes?</h3>
<p>Ideally, the locator is updated in the corresponding page object rather than in every test that uses the element.</p>
<h3>Q12. Should assertions be written inside Page Objects?</h3>
<p>Assertions are generally better kept in the test or dedicated validation layer, while page objects provide methods that expose useful application state.</p>
<h3>Q13. What is Fluent POM?</h3>
<p>Fluent POM allows page methods to return page objects or the current page object so that actions can be chained.</p>
<h3>Q14. What is a component object?</h3>
<p>A component object represents a reusable UI component such as a header, menu, search bar, or product card.</p>
<h3>Q15. What is the difference between POM and PageFactory?</h3>
<p>POM is a design pattern. PageFactory is an implementation approach historically used with Selenium's Page Object design to initialize WebElement fields annotated with <code>@FindBy</code>.</p>
<hr>
<h2>83. POM Best-Practice Checklist</h2>
<ul>
<li>Use separate page classes.</li>
<li>Keep locators private.</li>
<li>Use meaningful locator names.</li>
<li>Use meaningful action methods.</li>
<li>Keep page methods focused.</li>
<li>Keep test data outside page objects.</li>
<li>Keep browser management separate.</li>
<li>Use explicit waits where necessary.</li>
<li>Avoid duplicate locators.</li>
<li>Avoid unnecessarily large page classes.</li>
<li>Use component objects for reusable UI sections.</li>
<li>Use TestNG for organized execution.</li>
<li>Use reporting and logging at framework level.</li>
<li>Use version control.</li>
<li>Keep the framework consistent across the project.</li>
</ul>
<hr>
<h2>84. Complete POM Execution Flow</h2>
<pre><code>Requirement
↓
Test Scenario
↓
Test Case
↓
TestNG Test
↓
BaseTest
↓
Driver Factory
↓
WebDriver
↓
Page Object
↓
Locator
↓
WebElement
↓
Browser Action
↓
Application
↓
Validation
↓
Report</code></pre>
<hr>
<h2>85. POM Quick Revision Table</h2>
<table border="1" cellpadding="8" cellspacing="0">
<tr><th>Concept</th><th>Quick Explanation</th></tr>
<tr><td>POM</td><td>Design pattern for organizing page interactions</td></tr>
<tr><td>Page Class</td><td>Represents a page or application component</td></tr>
<tr><td>Locator</td><td>Identifies a web element</td></tr>
<tr><td>Page Method</td><td>Performs an action on the page</td></tr>
<tr><td>Constructor</td><td>Receives WebDriver</td></tr>
<tr><td>Test Class</td><td>Contains test scenarios</td></tr>
<tr><td>BaseTest</td><td>Handles common setup and teardown</td></tr>
<tr><td>Data-Driven</td><td>Provides multiple test-data sets</td></tr>
<tr><td>Keyword-Driven</td><td>Provides reusable action keywords</td></tr>
<tr><td>Hybrid Framework</td><td>Combines multiple automation approaches</td></tr>
</table>
<hr>
<h2>86. Course Resources</h2>
<p>JustAcademy's Selenium Training includes Page Object Model as part of its Selenium automation framework curriculum, together with Data-Driven Testing, Keyword-Driven Testing, Hybrid Framework Design, reusable test architecture, reporting, logging, debugging, Selenium Grid, cross-browser testing, and CI/CD topics.</p>
<p><a href="https://www.justacademy.co/course-detail/selenium-training" target="_blank" rel="noopener noreferrer">Selenium Training</a></p>
<p><a href="https://www.justacademy.co/register-for-course-demo" target="_blank" rel="noopener noreferrer">Register for Course Demo</a></p>
<hr>
<h2>87. Final Summary</h2>
<p><strong>Page Object Model (POM)</strong> is a design pattern that organizes Selenium automation by representing application pages or reusable UI components as classes. These classes contain page-specific locators and methods, while test classes focus primarily on test scenarios and validations.</p>
<p>The major benefits of POM are <strong>maintainability, reusability, readability, reduced duplication, better organization, and scalability</strong>. POM can be combined with TestNG, Data-Driven Testing, Keyword-Driven Testing, Maven, reporting, logging, Selenium Grid, and CI/CD to create a complete Selenium automation framework.</p>
<hr>
<h2>88. One-Line Revision</h2>
<p><strong>POM = Separate Page Locators + Page Actions from Test Logic to create reusable, readable, maintainable, and scalable Selenium automation.</strong></p>
<hr>
<h2>89. Important Learning Flow</h2>
<pre><code>Selenium WebDriver
↓
Locators
↓
WebElements
↓
TestNG
↓
Page Object Model
↓
Data-Driven Testing
↓
Keyword-Driven Testing
↓
Hybrid Framework
↓
Reporting & Logging
↓
Selenium Grid
↓
Git + Maven
↓
Jenkins + CI/CD
↓
Real-Time Automation Project</code></pre>
</div>